// 属性访问控制
// ES不同版本对原型的解析不同，esnext中属性放到了实例中原型中不存在
// function defaultValue(value:any){
//     return function(target,propertyKey){
//         let val = value;
//         const getter = function(){
//             return val;
//         }
//         const setter = function(newValue){
//             val = newValue
//         }
//         // 新的版本中，属性都加在了实例中，监控不到原型上的属性了
//         Object.defineProperty(target,propertyKey,{
//             enumerable:true,
//             configurable:true,
//             get:getter,
//             set:setter
//         })
//     }
// }
class Settings{
    // @defaultValue('dark')
    theme:string;
    // @defaultValue(1000 * 10)
    timeout:number;
}
const setting = new Settings();
// 验证不同 ESM版本的 原型上是否含有属性
// 获取实例上是否含有theme
console.log(Object.getOwnPropertyDescriptor(setting,'theme'));  // {value:undefined,writable:true,enumerable:true,configurable:true}
// 获取类的原型上是否含有 theme
console.log(Object.getOwnPropertyDescriptor(Settings.prototype,'theme'));   //undefined

console.log(setting.theme);
console.log(setting.timeout);
setting.theme = 'light';
console.log(setting.theme);


// 可以改用下面方式，用类解释器
function classDefaultValues(values:{[key:string]:any}){
    return function<T extends {new (...args:any[])}>(constructor:T){
        return class extends constructor{
            constructor(...args:any){
                super(...args);
                for(let k in values){
                    if(this[k] === undefined){
                        this[k] = values[k]
                    }
                }
            }
        }
    }
}
@classDefaultValues({
    name:'小猫',
    weight:100
})
class Animal{
    public name:string
    public weight:number
}
const cat = new Animal();
console.log(cat);